package com.base.cn.platform.os.common.rsa;

import com.base.cn.platform.os.common.j2cache.CustomCacheChannel;
import com.base.cn.platform.os.common.j2cache.J2CacheRegion;
import com.base.cn.platform.os.common.md5.MD5;
import com.base.cn.platform.os.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.security.Key;
import java.util.HashMap;
import java.util.Map;

/**
 * 前台应用Rsa工具类
 *
 * @author s.li
 * @date 2019/03/15
 */
@Slf4j
public class WebRsaUtils {
    private static String sign = null;
    private static long time = System.currentTimeMillis();
    /**
     * 获取客户端签名
     * @param customCacheChannel 缓存工具类
     * @param privateKey 私钥
     * @return 签名
     */
    public static String getClientSign(CustomCacheChannel customCacheChannel, String privateKey){
        String sign = MD5.getMD5(System.currentTimeMillis()+ StringUtils.getRandomString(32)+privateKey);
        customCacheChannel.set(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),sign,privateKey);
        return sign;
    }

    /**
     * 解密
     * @param cacheChannel 缓存
     * @param sign 签名
     * @param dataContext 加密的内容
     * @return 解密的内容
     * @throws Exception
     */
    public static String decrypt(CustomCacheChannel cacheChannel, String sign, String dataContext, boolean  finish) throws Exception{
        if(!StringUtils.isNotEmpty(sign)){
            return dataContext;
        }
        if(StringUtils.isNotEmpty(dataContext)){
            //获取私钥
            String privateKey = (String)cacheChannel.get(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),sign).getValue();
            log.info("--------------privateKey:"+privateKey);
            //解密密码
            if(StringUtils.isNotEmpty(privateKey)){
                byte[] decodedData = RSAUtils.decryptByPrivateKey(dataContext, privateKey);
                dataContext = new String(decodedData);
                log.info("-----------------dataContext:"+dataContext);
            }
        }
        if(finish){
            //删除缓存
            //cacheChannel.evict(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),sign);
        }
        return dataContext;
    }

    /**
     * 公钥加密
     * @param dataContext
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encrypt(String dataContext,String publicKey) throws Exception{
        byte[] encryptData = RSAUtils.encryptByPublicKey(dataContext,publicKey);
        return RSAUtils.encryptBASE64(encryptData);
    }

    /**
     * 获取登录页面的公钥和签名
     * @param customCacheChannel
     * @return
     * @throws Exception
     */
    public static Map<String,String> getRSAData(CustomCacheChannel customCacheChannel) throws Exception{
        long _time = System.currentTimeMillis();
        boolean status = false;
        String privateKey;
        String publicKeyKey =null;
        if(sign==null || (_time - time) >= (25 * 60 * 1000)){//临时缓存25分钟（要小于Redis的缓存时间）
            status = true;
        }else{
            privateKey = (String)customCacheChannel.get(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),sign).getValue();
            publicKeyKey = (String)customCacheChannel.get(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),sign+"public").getValue();
            if(privateKey ==null || publicKeyKey==null){
                status = true;
            }
        }
        if(status){
            //获取公钥、私钥
            Map<String, Key> keyMap = RSAUtils.initKey();
            String _publicKey = RSAUtils.getPublicKey(keyMap);
            String _privateKey = RSAUtils.getPrivateKey(keyMap);
            //获取客户端签名
            String _sign = getClientSign(customCacheChannel,_privateKey);
            //缓存公钥
            customCacheChannel.set(J2CacheRegion.THIRTY_MINUTE_REGION.getKey(),_sign+"public",_publicKey);
            sign = _sign;
            time = System.currentTimeMillis();
            publicKeyKey = _publicKey;
        }
        Map<String,String> dataMap  = new HashMap<>();
        dataMap.put("publicKey",publicKeyKey);
        dataMap.put("sign",sign);
        log.info("----------------publicKeyKey:"+publicKeyKey);
        log.info("----------------sign:"+sign);
        return dataMap;
    }
}
